﻿using System;
using agsXMPP;
using agsXMPP.protocol.client;
using sharpxbot.Core.Messaging;
using sharpxbot.Core.Security;
using sharpxbot.Plugins.Context;
using sharpxbot.Utils.Logging;

namespace sharpxbot.Plugins.Base
{
    /// <summary>
    /// Some guids for core plugins:
    //5c26b11f-8433-4cab-b6b9-77574c2d75a7 - SystemInfoPlugin
    //6feb5ed3-291f-4572-914b-88e6051555d1 - NickSpamFilterPlugin
    //a0c157f7-9d8d-4e79-80d9-ba29e1349778 - MucAdminPlugin
    //22aae290-7925-4e29-a8dc-052730bd9c30 - GroupChatRulesPlugin
    //97e31b3e-b843-4760-a729-d1c33567ae78 - TrafficLimiterPlugin
    //17381042-9d4a-4e78-84c0-4c4b39348a43 - WebLinksPlugin
    //464d4d1d-7cc3-4140-8c23-6305b17fe875
    //c26ee58f-3a4e-48e7-94d8-dc8c7e1688b9
    //972de120-09b9-4784-9cad-f6f3cd7dcc26
    //b9ff2055-9384-4dd6-a44a-833f727dd8e0
    //cd27b830-f8b5-4d01-a5d1-95a09df1bb76
    //15e63885-695d-4cf2-a891-ba30edd7f585
    //852fef96-d4ba-4030-9573-748406abe309
    //7fa905a2-e0be-480a-b6f5-f6ce0340ff7d
    //a7dc71fc-50fb-48fc-b81b-679bbed30c54
    //3f0e15f4-faea-4675-bd7d-87bfc0c3d9e2
    //0ff13205-9309-440c-885a-84a06b8a0b0b
    //7fcfb5ea-c089-4aa5-9256-3a421bafa07b
    //1365e31f-2cb4-4b0c-b0a3-ce5ae9874475
    //4916fb63-f658-49b8-b84e-7372441494ed
    //ba2040f7-24b8-4281-971c-7573f3b2b24c
    //e2509ae7-c64d-4737-b1d5-48cb44bd4ba8
    //9d0744cc-2150-4c63-8874-c07e10763734
    //9bcc8d6a-8a51-41fd-913f-5c4fc1495821
    //f87121c1-2f17-49dc-924b-abc9754bd3e7
    //eedf5baa-011a-4827-a1ab-3143b5805ba8
    //644e1ddf-44d7-4b1a-bd0a-fc90bad04689
    //a3c484e5-c6bd-45d2-b5c2-0a28dd4e79b4
    //d3cc35cd-030a-45c5-9c36-da91a251fbdc
    //c435a9ea-1361-4ccc-b20c-ebbf02dd3fa7
    //b2eaa382-b23d-445e-90a1-8b263c650cf4
    //b307d104-ed3b-4e75-aa04-0796835606f2
    //f7715127-6e36-44cb-95f2-878064845a08
    //b9092099-5580-4cd8-82e2-efab47cbcfdb
    //35387d16-75f3-4703-a515-7e6d42241815
    //542ecefe-ceb7-42b9-9fa6-c31ca2828a26
    //b89bd02c-3f74-4a10-b855-76b7b490dd5b
    //28ec93c8-c6e0-4624-9e18-8740a0f4e4a0
    //7d52f4bc-9960-43ec-8412-985b3679cebc
    //5fddd170-2271-42b2-aaee-21c7067be910
    //18fb6d2d-32d9-49eb-b070-bd5d3b0483fd
    //08faf88f-aa77-41e9-858c-f9ffd50ac61f
    //9e8ea1dd-2205-47b6-b3aa-9152fc95c6d0
    //c7e9fa86-7a0c-436a-9a0d-6d5c1cffca98
    //55c6e46f-a5d2-4f4f-a539-6bfd0e0bf3aa
    //4a5d3fc4-3e94-4e4a-b5c5-0ccd13ca1ff8
    //056347c3-2d8e-4393-a69d-d283ee56d09c
    //f4db14da-30bc-4ea6-b732-c6299a33a233
    //d3b49477-e22c-4cb2-94a5-e3d56ea1fee0
    //5ecdc1f0-ccc7-4cc3-94d4-d55dab6d421b
    /// </summary>
    public abstract class AbstractPlugin : IPlugin
    {
        public AbstractPlugin(IPluginContext context)
        {
            if (context == null)
                throw new NullReferenceException("Illegal null-reference plugin context");

            this.Context = context;
        }

        #region Protected methods

        /// <summary>
        /// Gets value indicating that given message was sent from group-chat participant using PM feature of group-chat
        /// </summary>
        /// <param name="msg">Message to be verified</param>
        /// <returns>True if this is PM from group-chat, false otherwise</returns>
        protected bool IsPrivateGroupChatMessage(Message msg)
        {
            if (msg == null)
                return false;

            if (msg.Type != MessageType.chat)
                return false;

            Jid privateJid = Context.GroupChats.GetPrivateUserJid(msg.From);
            return privateJid != null;
        }

        /// <summary>
        /// Gets value indicating that given message is sent into group-chat
        /// </summary>
        /// <param name="msg">Message to be verified</param>
        /// <returns>True if this is group-chat message, false otherwise</returns>
        protected bool IsGroupChatMessage(Message msg)
        {
            if (msg == null)
                return false;

            return msg.Type == MessageType.groupchat;
        }

        /// <summary>
        /// Gets value indicating whether given presence packet is sent from group-chat's participant
        /// </summary>
        /// <param name="p">Presence packet to be verified</param>
        /// <returns>True if presence packet is sent by some group-chat participant false otherwise</returns>
        protected bool IsGroupChatPresence(Presence p)
        {
            if (p == null)
                return false;

            if (p.MucUser == null)
                return false;

            if (p.MucUser.Item == null)
                return false;

            return true;
        }

        #endregion

        #region IPlugin Members

        public IPluginContext Context { get; private set; }

        public abstract PluginPermissions NeededPermissions { get; }

        public abstract string Name { get; }

        public abstract string Author { get; }

        public abstract Guid GUID { get; }

        public abstract string Description { get; }

        public abstract string Usage { get; }

        #endregion

        #region IProcessor Members

        public abstract void ProcessMessage(Message message);

        public abstract void ProcessPresence(Presence presence);

        public void ProcessMessage(XmppMessage message)
        {
            if (message == null)
                return;

            try
            {
                if (message.Presence != null)
                    ProcessPresence(message.Presence);
                else if (message.Message != null)
                    ProcessMessage(message.Message);
            }
            catch (Exception ex)
            {
                Logger.Write("Plugin unhandled exception", ex, LogMessageType.Fatal);
            }
        }

        #endregion
    }
}
